#!/opt/local/bin/perl

# Pass messages recieved from AIM onto Growl.

# Usage screen name and password as it's two arguments.
#    ./AIM2Growl <screen_name> <password>

# Useful listening to notification bots.
# Create a new screen name just for this.
# Manage the bots with a traditional AIM client.

# I've noticed that this will start Growl if it's
# not running.  I suspect there are scenarios were
# it loses the connection to AIM and doesn't notice.

# Some otification bots:
#  Monitor RSS:
#   http://www.cs.cornell.edu/People/egs/beehive/corona/
#  Monitor others:
#   http://twitter.com/

# See also:
#   http://www.magdalar.net/projects/aimrelay/

# Improvements, comments, suggestions, other notification bots:
#     <bhyde@pobox.com>


use warnings;
use strict;
use Net::OSCAR;
use Mac::Growl ':all';
use Encode;
use HTML::Obliterate qw(remove_html);

my $GrowlName = 'AIM2Growl';
my $screenname;
my $password;
my $oscar;
my $backoff = 1;
my $max_backoff = 122;
my $sticky = 0;
my $logGrowl = 1;

sub Growl {
  my ($who, $msg) = @_;
  PostNotification($GrowlName,
		   'msg',
		   encode('utf8', $who),
		   encode('utf8', remove_html($msg)),
		   $sticky);
  print "growl: $who: $msg\n" 
    if $logGrowl;}

sub on_im {
  my ($oscar, $sender, $message, $is_away) = @_;
  print "$sender: $message\n";
  Growl($sender, $message);}

sub on_error {
   my ($oscar, $conn, $err, $desc, $fatal) = @_;
   print "error: $desc\n";
   Growl("AIM2Growl", "Error: $desc");
   create_oscar_client() if $fatal > 0;}


sub create_oscar_client {
  if ($backoff > 1){
    print "backing off for $backoff seconds\n";
    sleep $backoff;}
  $backoff = $max_backoff < $backoff * 2 ? $max_backoff : $backoff *2;
  $oscar = new Net::OSCAR;
  $oscar->timeout(10);
  $oscar->set_callback_im_in(\&on_im);
  $oscar->set_callback_signon_done(\&on_signon_done);
  $oscar->set_callback_error(\&on_error);
  print "Signing on: $screenname\n";
  $oscar->signon($screenname, $password);}

sub on_signon_done {
#   my ($oscar) = @_;
  print "Connected\n";
  Growl("AIM2Growl", "$screenname is now listening");
  $backoff = 1;}

sub main {
  print STDERR "Starting\n";
  ($screenname, $password) = @_;
  RegisterNotifications($GrowlName, ['msg'], ['msg']);
  create_oscar_client();
  while(1){
    $oscar->do_one_loop();}}

main(@ARGV);
